'''
Created on Dec 22, 2011

@author: u
'''

import config
import euclid

xmin, ymin = 0, 0
xmax, ymax = 2, 2

block_size = 25. #size of a block in world units
#center of (0, 0) block
start_loc = block_size / 2., block_size / 2.


#all client are at the same eight
default_height = 2.

def number_of_blocks():
    return (xmax - xmin + 1) * (ymax - ymin + 1)

def neighbours(blocks, coord):
    """
    returns adjacent blocks with their servers,
    if server is not known yet,
    we return a null server
    """
    
    x, y = coord
    
    result = []
    
    for i in [-1, 0, 1]:
        for j in [-1, 0, 1]:
            if i == 0 and j == 0:
                continue
            
            u = x + i
            v = y + j
            
            try:
                check_bounds(u, v)
                result.append(((u, v), blocks.get((u, v), None)))
            except BlockOutOfBound:
                pass
                
    return result

def neighbour_coords(neighs):
    """
    returns neighbours without server addresses
    """
    
    result = []
    
    for val in neighs:
        coords, _ = val
        result.append(coords)
                
    return result

def inside_block(block_coord, position):
    """
    returns True the position is inside the given block
    """
    
    return world_to_block(position) == block_coord

class BlockOutOfBound(Exception):
    pass

def check_bounds(x, y):
    if x < xmin or x > xmax or y < xmin or y > xmax:
        raise BlockOutOfBound()

def world_to_block(position):
    """
    returns the block corresponding to a world coord
    """

    x, y = position
    x, y = int(x / block_size), int(y / block_size)
    
    check_bounds(x, y)
    return x, y

def block_to_world(coord):
    x, y = coord
    return x * block_size, y * block_size
    
def block_list():
    for i in range(xmin, xmax + 1):
        for j in range(ymin, ymax + 1):
            yield i, j
            
def format_blocks(blocks):
    """
    returns a json friendly list of blocks and servers
    """
    
    result = []
    
    for coord in block_list():
        result.append((coord, blocks[coord]))
        
    return result

def unformat_blocks(blocks):    
    return dict((tuple(coord), host) for coord, host in blocks)
            
def blocks_ready(blocks):
    """
    returns True if all blocks have a server
    """
    for val in blocks.values():
        if val is None:
            return False
        
    return True

def block_corners(coord):
    """
    returns the coordinates of the four corners of a block
    """
    
    x, y = block_to_world(coord)
    
    return [(x, y), (x + block_size, y),
            (x, y + block_size), (x + block_size, y + block_size)]

def block_intersect(blocks, position):
    """
    returns the list of blocks an aura intersects
    """
    
    position = euclid.Vector2(*position)

    neigh = neighbours(blocks, block_to_world(position.xy))
    
    result = []
    
    for neigh_coord in neigh:
        corners = block_corners(neigh_coord)
        
        corner_distances = sorted(((position - euclid.Vector2(cx, cy)).magnitude()) for cx, cy in corners)
        
        if corner_distances[0] < config.aura_size * config.aura_size:
            result.append(neigh_coord)
            
    return result